#ifdef IMQ_PTHREAD
#include <pthread.h>
#endif

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>

#include "mtqLog.h"
#include "mtqcommon.h"

extern char **environ;

#ifdef IMQ_PTHREAD
/* mutex for getenv_r */
pthread_mutex_t gMutexEnv;
static pthread_once_t gOnce = PTHREAD_ONCE_INIT;

/**
 * thread_init
 */
static void _threadInit(void)
{
    pthread_mutexattr_t attr;

    pthread_mutexattr_init(&attr);
    pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
    pthread_mutex_init(&gMutexEnv, &attr);
    pthread_mutexattr_destroy(&attr);
}
#endif

/**
 * getenv_r
 */
int getenv_r(char *aBuf, int iBufLen, const char *aName)
{
    int i, iLen1, iLen2;

#ifdef IMQ_PTHREAD
    pthread_once(&gOnce, _threadInit);
#endif

    iLen1 = strlen(aName);

#ifdef IMQ_PTHREAD
    pthread_mutex_lock(&gMutexEnv);
#endif

    for (i = 0; environ[i] != NULL; i++)
    {
        if ((strncmp(aName, environ[i], iLen1) == 0) &&
            (environ[i][iLen1] == '='))
        {
            iLen2 = strlen(&environ[i][iLen1 + 1]);
            if (iLen2 >= iBufLen)
            {
#ifdef IMQ_PTHREAD
                pthread_mutex_unlock(&gMutexEnv);
#endif
                return -104;
            }

            strcpy(aBuf, &environ[i][iLen1 + 1]);
#ifdef IMQ_PTHREAD
            pthread_mutex_unlock(&gMutexEnv);
#endif

            return iLen2;
        }
    }
#ifdef IMQ_PTHREAD
    pthread_mutex_unlock(&gMutexEnv);
#endif

    return -101;
}

/**
 * _mtqTrimSpace
 */
int _mtqTrimSpace(char *aBuf)
{
    if (aBuf == NULL)
    {
        IMQEDEBUG("Argument [aBuf] is NULL");

        return -100;
    }
    IMQDDEBUG("The space in front or end of string [%s] will be trimed", aBuf);

    int i = 0;
    int j = 0;
    int ilLen = strlen(aBuf);

    for ( ; i < ilLen; i++)
    {
        j = i;
        if ((aBuf[i] != ' ') && (aBuf[i] != '\t') && (aBuf[i] != '\n'))
        {
            for ( ; i < ilLen; i++)
            {
                aBuf[i - j] = aBuf[i];
            }

            break;
        }
    }

    i = ilLen - j - 1;
    for ( ; i >= 0; i--)
    {
        if ((aBuf[i] != ' ') && (aBuf[i] != '\t') && (aBuf[i] != '\n'))
        {
            break;
        }
    }
    memset(&aBuf[i + 1], 0, (ilLen - i - 1));

    IMQDDEBUG("After trimed space, the result is [%s]", aBuf);

    return 0;
}

/**
 * Trim annotation
 */
int _mtqTrimAnnotation(char *aBuf)
{
    if (aBuf == NULL)
    {
        IMQEDEBUG("Argument [aBuf] is NULL.");

        return -100;
    }

    IMQDDEBUG("The annotation ['#'] of the  string [%s] will be trimed", aBuf);

    char *pIndex = strchr(aBuf, '#');
    if (pIndex != NULL)
    {
        memset(pIndex, 0, strlen(pIndex));
    }

    IMQDDEBUG("The annotation ['#'] of the string [%s] has been trimed", aBuf);

    return 0;
}

/**
 * Parse IP address
 */
int _mtqParseIPAddr(const char *aIP, int *iData1, int *iData2, int *iData3, int *iData4)
{
    if (aIP == NULL)
    {
        IMQEDEBUG("Argument [aIP] is NULL");
        
        return -1;
    }
    IMQDDEBUG("The IP address [%s] will be parsed", aIP);

    if (strlen(aIP) > 16)
    {
        IMQEDEBUG("IP address [%s] is illegal", aIP);

        return -100;
    }

    int i = 0;
    int j = 0;
    for ( ; i < strlen(aIP); i++)
    {
        if ((aIP[i] != '.') && (!isdigit(aIP[i])))
        {
            IMQEDEBUG("aIP [%s] is illegal", aIP);
            
            return -100;
        }

        if (aIP[i] == '.')
        {
            j++;
        }
    }

    if (j != 3)
    {
        IMQEDEBUG("aIP [%s] is illegal", aIP);
            
        return -100;
    }

    int ilData1, ilData2, ilData3, ilData4;
    int ilRet = sscanf(aIP, "%d.%d.%d.%d", &ilData1, &ilData2, &ilData3, &ilData4);
    if (ilRet != 4)
    {
        IMQEDEBUG("IP address [%s] is illegal", aIP);

        return -100;
    }

    if ((ilData1 < 0) || (ilData1 > 255) || (ilData2 < 0) || (ilData2 > 255) ||
        (ilData3 < 0) || (ilData3 > 255) || (ilData4 < 0) || (ilData4 > 255))
    {
        IMQEDEBUG("IP address [%s] is illegal", aIP);
        
        return -100;
    }

    if (iData1 != NULL)
    {
        *iData1 = ilData1;
    }
    if (iData2 != NULL)
    {
        *iData2 = ilData2;
    }
    if (iData3 != NULL)
    {
        *iData3 = ilData3;
    }
    if (iData4 != NULL)
    {
        *iData4 = ilData4;
    }

    IMQDDEBUG("Parse IP address [%d.%d.%d.%d] success",
        *iData1,
        *iData2,
        *iData3,
        *iData4);

    return 0;
} 

